#include "CentealCache.hpp"
#include "PageCache.hpp"
CentealCache CentealCache::_sInst;
//获取一个非空的span
Span* CentealCache::GetOneSpan(SpanList& list,size_t size)
{
    //查看当前的spanlist中是否还有未分配对象的span
    Span* it = list.Begin();
    while (it!=list.End())
    {
       if(it->_freeList!=nullptr)
       {
            return it; 
       }
       else{
            it=it->_next;
       }
    } 
    //没有空闲span，向pagecache要
    Span*span=PageCache::GetInstance()->NewSpan(SizeClass::NumMovePage(size));//一次要几页呢？
    //算span的地址
    //通过页号计算页的起始地址，结束结束地址和内存大小
    char* start=(char*)(span->_pageId<<PAGE_SHIFT);//用页号乘一页的大小 
    size_t bytes =span->_n<<PAGE_SHIFT;//计算一个span的大小
    char* end=start+bytes;
    //得到一个span，把span切成一块一块的挂起来
    //1.先切一块，方便做尾插
    span->_freeList = start;
    start+=size;
    void*tail=span->_freeList;
    while (start<end)
    {
        NextObj(tail) = start;
        tail = start;
        start+=size;
    }
    list.PushFront(span);
    return span;
}
// 从中心缓存获取一定数量的对象给thread cache
size_t CentealCache::FetchRangeObj(void *&start, void *&end, size_t n/*batchNum*/, size_t size)
{
    //在哪个位置？
    size_t index =SizeClass::Index(size);
    //加锁
    _spanLists[index]._mtx.lock();

    Span* span = GetOneSpan(_spanLists[index],size);
    assert(span);
    assert(span->_freeList);
    //从span中获取n个对象，如果不够n个，有多少拿多少
    start=span->_freeList;
    end=start;
    size_t i = 0;
    size_t actualNum=1;//可能自由链表中对象数量不够，那就需要知道实际数量了
    while(i < n-1&&NextObj(end)!=nullptr)
    {
        end=NextObj(end);
        i++;
    }
    span->_freeList = NextObj(end);
    NextObj(end)=nullptr;

    _spanLists[index]._mtx.unlock();
    return actualNum;
}